6장 컴포넌트 반복


데이터 배열을 컴포넌트 배열로 변환

map 함수 이용해서 배열들을 컴포넌트로 구성된 배열을 생성할 수 있다.

const IterationSample = () => {
  const names = ["눈사람", "얼음", "눈", "바람"];
  const names2 = [
    <li>눈사람</li>,
    <li>얼음</li>,
    <li>눈</li>,
    <li>바람바람</li>,
  ];
  const name3 = [
    "<li>눈사람</li>",
    "<li>얼음</li>",
    "<li>눈</li>",
    "<li>바람바람</li>",
  ];
  const nameList = names.map((name) => <li>{name}</li>);
  return (
    <ul>
      {nameList}(
      {names2}
    </ul>
  );
};

name3 처럼 문자열로 넣어줘도 될 줄 알았는데, 안됐다. react로 작성된 코드들은 어디서든 JSX가 적용되는 모양이다.
브라우저에 잘 나오지만, key prop이 없다는 에러가 발생하낟.

key

리액트에서 key는 컴포넌트 배열을 렌덩링 할때 어떤 원소에 변동이 있었는지 알아내기 위해 사용함. key 없으면 virtual DOM이랑 비교할 때, 리스트를 순차적으로 비교하지만, key가 있으면 key 값 사용해서 빠르게 변화 감지 할 수 있음.

함수 내부에서 컴포넌트 props를 설정하듯이 설정하면 됨.
key 값은 언제나 유일해야한다.

const IterationSample = () => {
  const names = ['눈사람', '얼음', '눈', '바람'];
  const namesList = names.map((name, index) => <li key={index}>{name}</li>);
  return <ul>{namesList}</ul>;
};

사실 이렇게 고유한 값이 없을 때, index 값을 key로 사용하면 비효율적임.
→ 고유값이 없으면 고유값을 만들어 사용해라.

데이터를 추가 구현

const IterationSample = () => {
  const [names, setNames] = useState([
    { id: 1, text: "눈사람" },
    { id: 2, text: "얼음" },
    { id: 3, text: "눈" },
    { id: 4, text: "바람" },
  ]);
  const [inputText, setInputText] = useState("");
  const [nextId, setNextId] = useState(5);

  const nameList = names.map((name) => <li key={name.id}>{name.text}</li>);

  const handleChange = (e) => {
    setInputText(e.target.value);
  };
  const handleClick = () => {
    setNames([...names, { id: nextId, text: inputText }]);
    setNextId(nextId + 1);
    setInputText("");
  };
  return (
    <div>
      <ul>{nameList}</ul>
      <input
        value={inputText}
        onChange={handleChange}
        placeholder="추가할 내용 입력"
      />
      <button onClick={handleClick}>추가</button>
    </div>
  );
};

데이터 제거 구현

데이터 불변성을 유지하면서 업데이트 해주기 위해서 배열의 내장함수 filter을 이용해야한다.
더블클릭을 하면 해당 요소가 삭제 된다.

	const handleDoubleClick = (e) => {
    const newNames = names.filter((name) => name.id != e.target.key);
    setNames(newNames);
  };
	const nameList = names.map((name) => (
    <li key={name.id} onDoubleClick={handleDoubleClick}>
      {name.text}
    </li>
  ));
	const handleDoubleClick = (id) => {
    const newNames = names.filter((name) => name.id != id);
    setNames(newNames);
  };
	const nameList = names.map((name) => (
    <li key={name.id} onDoubleClick={() => handleDoubleClick(name.id)}>
      {name.text}
    </li>
  ));

위와 같은 이유로 name.id를 인자로 넘겨주는 식으로 호출하는걸로 바꿨더니 잘 된다.